const CANVAS_HEIGHT = 1024;

export default class InterPic {
	constructor(viewer) {
		this.viewer = viewer;
		this.isLoadData = false;
		this.dataInfo = {
			LonMin: 0,
			LonMax: 0,
			LatMin: 0,
			LatMax: 0,
			DLon: 0,
			DLat: 0,
			LonNums: 0,
			LatNums: 0,
			LonStep: 0,
			LatStep: 0,
			UV: [], // UV分量 [i][j]->([i][j][0]-U [i][j][1]-V [i][j][2]-Speed)

			// 色斑图绘图区设置
			picWidth: 0,
			picHeight: 0,
			picXStep: 0,
			picYStep: 0,
		};

		// todo 待传入
		this.picInfo = {
			valueAry: [],
			rgbAry: [],
		};
		this.picInfo.valueAry.reverse();
		this.picInfo.rgbAry.reverse();

		this.rectangle = null;
		this.range = []; //四角坐标(地球背面)
		this.image = null;
	}

	// 处理风场数据，计算风速
	loadDataInfo(param) {
		this.isLoadData = false;
		const { dataInfo, colorInfo, isWindy = false } = param;
		if (
			dataInfo.Bound.length < 7 ||
			dataInfo.Bound[2] < 2 ||
			dataInfo.Bound[3] < 2 ||
			dataInfo.Bound[4] < 0 ||
			dataInfo.Bound[5] < 0
		) {
			return;
		}

		if (
			isWindy &&
			dataInfo.DataAry.length !==
				2 * dataInfo.Bound[2] * dataInfo.Bound[3]
		) {
			return;
		}

		// ******************************************************************************
		// 初始化数据信息
		this.isWindy = isWindy;
		this.dataInfo.LonMin = dataInfo.Bound[0];
		this.dataInfo.LatMin = dataInfo.Bound[1];
		this.dataInfo.LonNums = dataInfo.Bound[2];
		this.dataInfo.LatNums = dataInfo.Bound[3];
		this.dataInfo.LonStep = dataInfo.Bound[4] / (dataInfo.Bound[2] - 1);
		this.dataInfo.LatStep = dataInfo.Bound[5] / (dataInfo.Bound[3] - 1);

		this.dataInfo.DLon = dataInfo.Bound[4];
		this.dataInfo.DLat = dataInfo.Bound[5];
		this.dataInfo.LonMax = dataInfo.Bound[0] + dataInfo.Bound[4];
		this.dataInfo.LatMax = dataInfo.Bound[1] + dataInfo.Bound[5];
		this.dataInfo.ValueScale = 1.0 / dataInfo.Bound[6];

		const range = [
			this.dataInfo.LonMin,
			this.dataInfo.LatMin,
			this.dataInfo.LonMax,
			this.dataInfo.LatMax,
		];
		if (range.toString() !== this.range.toString()) {
			this.range = range;
			this.initPic("interPic", "");
		}

		this.dataInfo.picHeight = CANVAS_HEIGHT;
		this.dataInfo.picWidth = Math.ceil(
			(CANVAS_HEIGHT * this.dataInfo.DLon) / this.dataInfo.DLat
		);
		this.dataInfo.picXStep =
			this.dataInfo.picWidth / (this.dataInfo.LonNums - 1);
		this.dataInfo.picYStep =
			this.dataInfo.picHeight / (this.dataInfo.LatNums - 1);
		this.dataInfo.UV = [];

		if (isWindy) {
			this.dataInfo.DataAry = [];
			for (let index = 0; index < this.dataInfo.LatNums; index++) {
				this.dataInfo.UV[index] = [];
				for (let j = 0; j < this.dataInfo.LonNums; j++) {
					this.dataInfo.UV[index].push(
						this._getUVSpeed(
							dataInfo.DataAry[
								index * this.dataInfo.LonNums * 2 + j * 2
							],
							dataInfo.DataAry[
								index * this.dataInfo.LonNums * 2 + j * 2 + 1
							]
						)
					);
				}
			}
		} else {
			this.dataInfo.UV = [];
			this.dataInfo.DataAry = dataInfo.DataAry;
		}

		// 初始化配色信息
		if (colorInfo.Values?.length) {
			if (colorInfo.Values[0] > colorInfo.Values[1]) {
				colorInfo.Values.reverse();
				colorInfo.Colors.reverse();
			}
			this.picInfo.valueAry = colorInfo.Values;
			this.picInfo.rgbAry = colorInfo.Colors;
		} else {
			this.picInfo.valueAry = [];
			this.picInfo.rgbAry = [];
		}

		this.isLoadData = true;
	}

	_getUVSpeed(u, v) {
		return [u, v, Math.sqrt(u * u + v * v)];
	}

	// 添加色斑图
	addInterPic(alpha = 255) {
		const c = document.createElement("canvas");

		const width = this.dataInfo.picWidth;
		const height = this.dataInfo.picHeight;
		const xStep = this.dataInfo.picXStep;
		const yStep = this.dataInfo.picYStep;
		c.width = width;
		c.height = height;
		const ctx = c.getContext("2d");

		const myImgData = ctx.createImageData(width, height);
		const len = myImgData.data.length;

		for (let index = 0; index < len; index += 4) {
			const y = Math.floor(index / 4 / width); //绘图区xy
			const x = (index / 4) % width;
			const py = (height - y) / yStep; //数据信息
			const px = x / xStep;
			const interValue = this._interBilinear(px, py);
			if (!interValue) {
				continue;
			}
			const rgba = this._getInterColor(interValue, alpha);
			myImgData.data[index] = rgba[0];
			myImgData.data[index + 1] = rgba[1];
			myImgData.data[index + 2] = rgba[2];
			myImgData.data[index + 3] = rgba[3];
		}
		ctx.putImageData(myImgData, 0, 0);
		// 更新色斑图
		this.updatePic(c);
	}

	// 初始化图片
	initPic(id, image) {
		// Primitive方式
		const instance = new Cesium.GeometryInstance({
			geometry: new Cesium.RectangleGeometry({
				rectangle: Cesium.Rectangle.fromDegrees(...this.range),
				vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
			}),
		});
		const primitive = new Cesium.Primitive({
			geometryInstances: instance,
			appearance: new Cesium.EllipsoidSurfaceAppearance({
				material: new Cesium.Material({
					fabric: {
						type: "Image",
						uniforms: {
							image,
						},
					},
				}),
			}),
		});
		this.rectangle = this.viewer.addPrimitive(id, primitive);
	}

	// 更新图片
	updatePic(image) {
		this.rectangle.appearance.material = new Cesium.Material({
			fabric: {
				type: "Image",
				uniforms: {
					image,
				},
			},
		});
	}

	// 更新图片配色
	updataPicColor(colors) {
		console.log(this.picInfo.rgbAry);
		this.picInfo.rgbAry = colors;
		console.log(this.picInfo.rgbAry);
		this.addInterPic();
	}

	// 插值
	_interBilinear(px, py) {
		const rowIndex = Math.floor(py);
		const colIndex = Math.floor(px);
		const rowIndex2 = rowIndex + 1;
		const colIndex2 = colIndex + 1;
		if (
			rowIndex < 0 ||
			rowIndex >= this.dataInfo.LatNums ||
			colIndex < 0 ||
			colIndex >= this.dataInfo.LonNums ||
			rowIndex2 < 0 ||
			rowIndex2 >= this.dataInfo.LatNums ||
			colIndex2 < 0 ||
			colIndex2 >= this.dataInfo.LonNums
		) {
			return null;
		}

		let g00;
		let g01;
		let g10;
		let g11;
		let result;

		const x = px - colIndex;
		const y = py - rowIndex;
		const rx = 1 - x;
		const ry = 1 - y;
		const a = rx * ry;
		const b = x * ry;
		const c = rx * y;
		const d = x * y;

		if (this.isWindy) {
			g00 = this.dataInfo.UV[rowIndex][colIndex];
			g01 = this.dataInfo.UV[rowIndex2][colIndex];
			g10 = this.dataInfo.UV[rowIndex][colIndex2];
			g11 = this.dataInfo.UV[rowIndex2][colIndex2];

			const u = g00[0] * a + g10[0] * b + g01[0] * c + g11[0] * d;
			const v = g00[1] * a + g10[1] * b + g01[1] * c + g11[1] * d;
			const s = u * u + v * v;
			result = Math.sqrt(s);
		} else {
			const cols = this.dataInfo.LonNums;
			g00 = this.dataInfo.DataAry[rowIndex * cols + colIndex];
			g01 = this.dataInfo.DataAry[rowIndex2 * cols + colIndex];
			g10 = this.dataInfo.DataAry[rowIndex * cols + colIndex2];
			g11 = this.dataInfo.DataAry[rowIndex2 * cols + colIndex2];
			result = g00 * a + g10 * b + g01 * c + g11 * d;
		}

		return result;
	}

	// 获取渐变色
	_getInterColor(value, a) {
		if (this.picInfo.valueAry === null) {
			return [0, 0, 0, 0];
		}
		const valueAry = this.picInfo.valueAry;
		const rgbAry = this.picInfo.rgbAry;

		const len = valueAry.length;
		const maxValue = valueAry[len - 1];
		const minValue = valueAry[0];

		let index = 0;
		let scale = 0;
		let r = 0,
			g = 0,
			b = 0;
		let r2 = 0,
			g2 = 0,
			b2 = 0;

		if (value > minValue && value <= maxValue) {
			for (let i = 1; i < len; i++) {
				if (value <= valueAry[i]) {
					index = i;
					scale =
						(value - valueAry[i - 1]) /
						(valueAry[i] - valueAry[i - 1]);
					break;
				}
			}
			r = rgbAry[index - 1][0];
			g = rgbAry[index - 1][1];
			b = rgbAry[index - 1][2];

			r2 = rgbAry[index][0];
			g2 = rgbAry[index][1];
			b2 = rgbAry[index][2];

			r = r + scale * (r2 - r);
			g = g + scale * (g2 - g);
			b = b + scale * (b2 - b);
		} else if (value > maxValue) {
			r = rgbAry[len - 1][0];
			g = rgbAry[len - 1][1];
			b = rgbAry[len - 1][2];
		} else if (value <= minValue) {
			return [0, 0, 0, 0];
		}
		return [r, g, b, a];
	}
}
